package com.michael.demos.base.base.java.datastructure;

/**
 * JAVA 基础数据类型
 *
 * @author Michael
 */
public class BaseDataTypeDemo {

    /**
     * <pre>
     * 原码、反码、补码的说明：
     * PS:以下数据为4位2进制数。4位2进制可用于表示 -8 ~ 7 的值
     *      1000[反] 表示-8，继承了-0的值，是一个扩充位。此时-8无法计算原码值
     *      计算机存储的数据均为补码
     * 1. 原码
     *      正数的原码就是本身
     *          6的原码 0110
     *      负数用最高位1表示负数
     *          -6的原码 1110
     * 2. 反码
     *      正数的反码与原码一样
     *          6的反码 0110
     *      负数的反码是将原码翻转
     *          -6的反码 1001
     * 3. 补码
     *      正数的补码与原码一样
     *          6的补码 0110
     *      负数的补码 = 反码+1
     *          -6的补码 1010
     * 4. TODO 计算机中存储的是补码形式
     *      如 6+(-6) = 0110 + 1010 = (1)0000 由于数位问题，最前面的1舍弃，最后结果为0
     *      如果用原码：0110 + 1110 = (1)0100 = 4
     *      如果用反码：0110 + 1001 = 1111[反] = 1000[原] = -0
     * </pre>
     */
    public static void main(String[] args) {

        System.out.println("JAVA的基础数据类型");
//        theInteger();
//        theFloat();
//        theBoolean();
//        theChar();
        unicode();
        System.out.println(isChinese('鿕'));
        System.out.println(isChinese('＄'));
    }

    public static void theChar() {
        System.out.println("\n=================================================================");
        System.out.println("char用于表示单个字符,用单引号");
        char a = 'a';
        char b = 'b';
        System.out.println("字母a与字母b的ASCII码值相加：" + (a + b));
        int chinese = '中';
        System.out.println(Integer.toHexString(chinese));
        System.out.println(chinese);
    }

    public static void unicode() {

        for (int i = 0; i < 2 << 15; i++) {
            if (i < 16) {
                System.out.println("\\u000" + Integer.toHexString(i) + " -> " + i + " -> " + (char) i);
            } else if (i < 16 << 4) {
                System.out.println("\\u00" + Integer.toHexString(i) + " -> " + i + " -> " + (char) i);
            } else if (i < 16 << 8) {
                System.out.println("\\u0" + Integer.toHexString(i) + " -> " + i + " -> " + (char) i);
            } else {
                System.out.println("\\u" + Integer.toHexString(i) + " -> " + i + " -> " + (char) i);
            }
        }

        /*
         *  常用范围说明
         *
         *  0 - 9   48 - 57     \u0030 - \u0039
         *  A - Z   65 - 90     \u0041 - \u005a
         *  a - z   97 - 122    \u0061 - \u007a
         *  常用中文    19968 - 40917   \u4e00 - \u9fd5 TODO 可能有误差
         */

//        char c = '\uffe8';
//        System.out.println(c);

//        Character.UnicodeBlock cjkUnifiedIdeographs = Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS;
//        Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A;
//        Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B;
//        Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION;
//        Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS;
//        Character.UnicodeBlock.GENERAL_PUNCTUATION;
    }

    // 根据Unicode编码完美的判断中文汉字和符号
    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        return (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION);
    }

    public static void theBoolean() {
        System.out.println("\n=================================================================");
        System.out.println("boolean只可以是true或者false,占用1字节。\n不能转换为任何类型");
    }

    public static void theFloat() {

        System.out.println("JAVA中符点数默认类型为 double");

        System.out.println("\n=================================================================");
        System.out.println("float取值范围: " + Float.MIN_VALUE + " ~ " + Float.MAX_VALUE + " 占用 4 字节");
        System.out.println("\n=================================================================");
        System.out.println("double取值范围: " + Double.MIN_VALUE + " ~ " + Double.MAX_VALUE + " 占用 8 字节");
        System.out.println("\n=================================================================");
        System.out.println("符点数演示");
        System.out.println("float f1 = 823828411f;");
        System.out.println("float f2 = f1 +1;");
        System.out.println("float f = 0.1f;");
        System.out.println("double d1 = 0.1;");
        System.out.println("double d2 = 0.1d;");
        System.out.println("double d3 = 2939849393593859348d;");
        System.out.println("double d4 = d3+1;");

        float f1 = 823828411f;
        float f2 = f1 + 1;
        float f = 0.1f;

        double d1 = 0.1;
        double d2 = 0.1d;

        double d3 = 2939849393593859348d;
        double d4 = d3 + 1;

        // 由于精度问题，f与d1/d2的值不相等
        System.out.println("f1 == f2? " + (f1 == f2 ? "true" : "false"));
        System.out.println("f == d1? " + (f == d1 ? "true" : "false"));
        System.out.println("f == d2? " + (f == d2 ? "true" : "false"));
        System.out.println("d1 == d2? " + (d1 == d2 ? "true" : "false"));
        System.out.println("d3 == d4? " + (d3 == d4 ? "true" : "false"));
        System.out.println("\n对于精度要求比较严格的场景请使用BigDecimal处理");

    }

    public static void theInteger() {

        System.out.println("\nJAVA中整数默认类型为 int");

        System.out.println("\n=================================================================");
        System.out.println("byte取值范围: " + Byte.MIN_VALUE + " ~ " + Byte.MAX_VALUE + " 占用 1 字节");
        System.out.println("128强制转换为byte的值为：" + (byte) 128);
        System.out.println("byte只能表示8位二进制数,128的二进制表示为 0 1000 0000,至少需要9位");
        System.out.println("强制转换为8位，取最后8位值重新计算byte表示的值，即为 -128(1000 0000[补])");

        System.out.println("\n=================================================================");
        System.out.println("short取值范围: " + Short.MIN_VALUE + " ~ " + Short.MAX_VALUE + " 占用 2 字节");
        System.out.println("同理：32768强制转换为short的值为：" + (short) 32768);

        System.out.println("\n=================================================================");
        System.out.println("int取值范围: " + Integer.MIN_VALUE + " ~ " + Integer.MAX_VALUE + " 占用 4 字节");
        System.out.println("同理：2147483648强制转换为int的值为：" + (int) 2147483648L);

        System.out.println("\n=================================================================");
        System.out.println("long取值范围: " + Long.MIN_VALUE + " ~ " + Long.MAX_VALUE + " 占用 8 字节");

        System.out.println("\n=================================================================");
        System.out.println("如果整数超过long的范围，使用BigInteger处理");
        System.out.println("\n=================================================================");

    }
}
